/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef __TREE_H__
#define __TREE_H__

#include <map>
#include "Saver.h"
#include "Object.h"
#include "Stream.h"

namespace liba
{
namespace xml
{

template<class K, class V>
class Tree : public ObjectUnicode
{
protected:
	typedef std::map<K, Tree*> Nodes;
	typedef std::map<K, V> Attributes;	
	
public:	
	Tree()
	{
	}

	~Tree()
	{
		for( typename Nodes::iterator it = nodes.begin(); it != nodes.end(); ++it )
		{
			delete it->second; it->second = 0;
		}
	}

	const Tree & operator[](const K & name)const
	{
		static Tree stub;
		typename Nodes::const_iterator it = nodes.find(name);
		if( it != nodes.end() )
			return *(it->second);
		else
			return stub;
	}

	Tree & operator[](const K & name)
	{
		static Tree stub;
		typename Nodes::const_iterator it = nodes.find(name);
		if( it != nodes.end() )
			return *(it->second);
		else
		{
			Tree * tree = new Tree();
			nodes.insert( typename Nodes::value_type( name, tree ) );
			return *tree;
		}
			
	}

	const V operator()(const K & name)const
	{
		static V stub;
		typename Attributes::const_iterator it = attributes.find(name);
		if( it != attributes.end() )
			return (it->second);
		else
			return stub;
	}

	V & operator()(const K & name)
	{
		return attributes[name];
	}
protected:
	virtual bool on_node( Provider * prov, const std::wstring & name )
	{		
		K key;
		if( converter::convert( name, &key ) )
			return prov->parse_object( &(*this)[key] );
		return false;
	}
	virtual bool on_attribute( Provider * prov, const std::wstring & name, const std::wstring & value )
	{
		K key;
		if( converter::convert( name, &key ) )
			return converter::convert( value, &(*this)(key) );
		return false;
	}

	virtual void on_save_attributes( xml::SaverBase * saver )const
	{
		typename Attributes::const_iterator it = attributes.begin();
		for( ; it != attributes.end(); ++it )
			saver->save_attribute( it->first, it->second );
	}

	virtual void on_save_nodes( xml::SaverBase * saver )const
	{
		typename Nodes::const_iterator it = nodes.begin();
		for( ; it != nodes.end(); ++it )
			saver->save_node( it->first, it->second );

	}
private:
	Nodes nodes;
	Attributes attributes;
};


} // namspace xml
} // namspace liba

using namespace liba;

#endif //__TREE_H__
